home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / examples / helpsigs / Lexer.lex < prev    next >
Encoding:
Text File  |  1997-08-18  |  11.9 KB  |  444 lines  |  [TEXT/R*ch]

  1. {
  2. open Fnlib Memory Config Mixture Const Parser;
  3.  
  4. (* For Quote/Antiquote --- object language embedding. *)
  5.  
  6. val quotation = ref false;
  7.  
  8. datatype lexingMode =
  9.     NORMALlm
  10.   | QUOTElm
  11.   | ANTIQUOTElm
  12. ;
  13.  
  14. val lexingMode = ref NORMALlm;
  15.  
  16. val parCount = Stack.new() : int Stack.t;
  17.  
  18. fun resetLexerState() =
  19. (
  20.   lexingMode := NORMALlm;
  21.   Stack.clear parCount
  22. );
  23.  
  24. (* For nesting comments *)
  25.  
  26. val comment_depth = ref 0;
  27.  
  28. (* The table of keywords *)
  29.  
  30. val keyword_table = (Hasht.new 53 : (string,token) Hasht.t);
  31.  
  32. val () =
  33. List.app (fn (str,tok) => Hasht.insert keyword_table str tok)
  34. [
  35.   ("abstraction",  ABSTRACTION),
  36.   ("abstype",      ABSTYPE),
  37.   ("and",          AND),
  38.   ("andalso",      ANDALSO),
  39.   ("as",           AS),
  40.   ("case",         CASE),
  41.   ("datatype",     DATATYPE),
  42.   ("do",           DO),
  43.   ("else",         ELSE),
  44.   ("eqtype",       EQTYPE),
  45.   ("end",          END),
  46.   ("exception",    EXCEPTION),
  47.   ("fn",           FN),
  48.   ("fun",          FUN),
  49.   ("handle",       HANDLE),
  50.   ("if",           IF),
  51.   ("in",           IN),
  52.   ("infix",        INFIX),
  53.   ("infixr",       INFIXR),
  54.   ("let",          LET),
  55.   ("local",        LOCAL),
  56.   ("nonfix",       NONFIX),
  57.   ("of",           OF),
  58.   ("op",           OP),
  59.   ("open",         OPEN),
  60.   ("orelse",       ORELSE),
  61.   ("prim_eqtype",  PRIM_EQTYPE),
  62.   ("prim_EQtype",  PRIM_REFTYPE),
  63.   ("prim_type",    PRIM_TYPE),
  64.   ("prim_val",     PRIM_VAL),
  65.   ("raise",        RAISE),
  66.   ("rec",          REC),
  67.   ("sig",          SIG),
  68.   ("signature",    SIGNATURE),
  69.   ("struct",       STRUCT),
  70.   ("structure",    STRUCTURE),
  71.   ("then",         THEN),
  72.   ("type",         TYPE),
  73.   ("val",          VAL),
  74.   ("while",        WHILE),
  75.   ("with",         WITH),
  76.   ("withtype",     WITHTYPE),
  77.   ("#",            HASH),
  78.   ("->",           ARROW),
  79.   ("|",            BAR),
  80.   (":",            COLON),
  81.   ("=>",           DARROW),
  82.   ("=",            EQUALS),
  83.   ("*",            STAR)
  84. ];
  85.  
  86. fun mkKeyword lexbuf =
  87.   let val s = getLexeme lexbuf in
  88.     Hasht.find keyword_table s
  89.     handle Subscript => ID s
  90.   end
  91. ;
  92.  
  93. val savedLexemeStart = ref 0;
  94.  
  95. val initial_string_buffer = CharArray.array(256, #"\000");
  96. val string_buff = ref initial_string_buffer;
  97. val string_index = ref 0;
  98.  
  99. fun reset_string_buffer() =
  100. (
  101.   string_buff := initial_string_buffer;
  102.   string_index := 0;
  103.   ()
  104. );
  105.  
  106. fun store_string_char c =
  107.   let open CharArray
  108.       val len = length (!string_buff)
  109.   in
  110.     if !string_index >= len then
  111.       let val new_buff = array(len * 2, #"\000") in
  112.         copy
  113.           { src = !string_buff, si = 0, len = NONE, dst = new_buff, di = 0 };
  114.         string_buff := new_buff
  115.       end
  116.     else ();
  117.     update(!string_buff, !string_index, c);
  118.     incr string_index
  119.   end;
  120.  
  121. fun get_stored_string() =
  122.   let open CharArray
  123.       val s = extract(!string_buff, 0, SOME (!string_index))
  124.   in
  125.     string_buff := initial_string_buffer;
  126.     s
  127.   end;
  128.  
  129. fun splitQualId s =
  130.   let open CharVector
  131.       val len' = size s - 1
  132.       fun parse n =
  133.         if n >= len' then
  134.           ("", s)
  135.         else if sub(s, n) = #"." then
  136.           ( normalizedUnitName (extract(s, 0, SOME n)),
  137.             extract(s, n + 1, SOME(len' - n)) )
  138.         else
  139.           parse (n+1)
  140.   in parse 0 end;
  141.  
  142. fun mkQualId lexbuf =
  143.   let val (qual, id) = splitQualId(getLexeme lexbuf) in
  144.     if id = "*" then
  145.       QUAL_STAR { qual=qual, id=id }
  146.     else
  147.       QUAL_ID   { qual=qual, id=id }
  148.   end
  149. ;
  150.  
  151. fun charCodeOfDecimal lexbuf i =
  152.   100 * (Char.ord(getLexemeChar lexbuf i) - 48) +
  153.    10 * (Char.ord(getLexemeChar lexbuf (i+1)) - 48) +
  154.         (Char.ord(getLexemeChar lexbuf (i+2)) - 48)
  155. ;
  156.  
  157. fun lexError msg lexbuf =
  158. (
  159.   resetLexerState();
  160.   raise LexicalError(msg, getLexemeStart lexbuf, getLexemeEnd lexbuf)
  161. );
  162.  
  163. fun constTooLarge msg lexbuf =
  164. (
  165.   resetLexerState();
  166.   lexError (msg ^ " constant is too large") lexbuf
  167. );
  168.  
  169. prim_val sml_word_of_string    : string -> word = 1 "sml_word_of_dec";
  170. prim_val sml_word_of_hexstring : string -> word = 1 "sml_word_of_hex";
  171.  
  172. fun notTerminated msg lexbuf =
  173. (
  174.   resetLexerState();
  175.   raise LexicalError (msg ^ " not terminated",
  176.                       !savedLexemeStart, getLexemeEnd lexbuf)
  177. );
  178.  
  179. fun skipString msg skip lexbuf =
  180.   let
  181.     val pos1 = getLexemeStart lexbuf
  182.     val pos2 = getLexemeEnd lexbuf
  183.   in
  184.     skip lexbuf;
  185.     resetLexerState();
  186.     raise (LexicalError(msg, pos1, pos2))
  187.   end
  188. ;
  189.  
  190. fun scanString scan lexbuf =
  191. (
  192.   reset_string_buffer();
  193.   savedLexemeStart := getLexemeStart lexbuf;
  194.   scan lexbuf;
  195.   setLexStartPos lexbuf (!savedLexemeStart - getLexAbsPos lexbuf)
  196. );
  197.  
  198. }
  199.  
  200. rule Token = parse
  201.     [^ `\000`-`\255`]
  202.       { lexError "this will be never called!" lexbuf }
  203.   | ""
  204.       { case !lexingMode of
  205.             NORMALlm =>
  206.               TokenN lexbuf
  207.           | QUOTElm =>
  208.               (scanString Quotation lexbuf;
  209.                case !lexingMode of
  210.                    NORMALlm =>
  211.                      QUOTER (get_stored_string())
  212.                  | ANTIQUOTElm =>
  213.                      QUOTEM (get_stored_string())
  214.                  | QUOTElm =>
  215.                      fatalError "Token")
  216.           | ANTIQUOTElm =>
  217.               AntiQuotation lexbuf
  218.       }
  219.  
  220. and TokenN = parse
  221.     [` ` `\n` `\r` `\t` `\^L`]  { TokenN lexbuf }
  222.   | "(*"
  223.       { savedLexemeStart := getLexemeStart lexbuf;
  224.         comment_depth := 1; Comment lexbuf; TokenN lexbuf
  225.       }
  226.   | "*)"
  227.       { lexError "unmatched comment bracket" lexbuf }
  228.   | "'" [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]+
  229.                 { TYVAR   (getLexeme lexbuf) }
  230.   | "0"         { ZDIGIT 0 }
  231.   | [`1`-`9`]   { NZDIGIT   (sml_int_of_string(getLexeme lexbuf)) }
  232.   | "0" [`0`-`9`]+
  233.                 { ZPOSINT2  (sml_int_of_string(getLexeme lexbuf))
  234.                   handle Fail _ => constTooLarge "integer" lexbuf
  235.                 }
  236.   | [`1`-`9`] [`0`-`9`]+
  237.                 { NZPOSINT2 (sml_int_of_string(getLexeme lexbuf))
  238.                   handle Fail _ => constTooLarge "integer" lexbuf
  239.                 }
  240.   | "~" [`0`-`9`]+
  241.                 { NEGINT    (sml_int_of_string(getLexeme lexbuf))
  242.                   handle Fail _ => constTooLarge "integer" lexbuf
  243.                 }
  244.   | "~"? "0x" [`0`-`9` `a`-`f` `A`-`F`]+
  245.                 { NEGINT    (sml_hex_of_string(getLexeme lexbuf))
  246.                   handle Fail _ => constTooLarge "integer" lexbuf
  247.                 }
  248.   | "0w" [`0`-`9`]+
  249.                 { WORD (sml_word_of_string(getLexeme lexbuf))
  250.                   handle Fail _ => constTooLarge "word" lexbuf
  251.                 }
  252.   | "0wx" [`0`-`9` `a`-`f` `A`-`F`]+
  253.                 { WORD (sml_word_of_hexstring(getLexeme lexbuf))
  254.                   handle Fail _ => constTooLarge "word" lexbuf
  255.                 }
  256.   | "~"? [`0`-`9`]+ (`.` [`0`-`9`]+)? ([`e` `E`] `~`? [`0`-`9`]+)?
  257.                 { REAL (sml_float_of_string (getLexeme lexbuf))
  258.                   handle Fail _ => constTooLarge "real" lexbuf
  259.                 }
  260.   | "\""
  261.       { scanString String lexbuf;
  262.         STRING (get_stored_string())
  263.       }
  264.   | "#\""
  265.       { scanString String lexbuf;
  266.         let val s = get_stored_string() in
  267.           if size s <> 1 then
  268.             lexError "ill-formed character constant" lexbuf
  269.           else ();
  270.           CHAR (CharVector.sub(s, 0))
  271.         end }
  272.   | "_"         { UNDERBAR }
  273.   | ","         { COMMA }
  274.   | "..."       { DOTDOTDOT }
  275.   | "{"         { LBRACE }
  276.   | "}"         { RBRACE }
  277.   | "["         { LBRACKET }
  278.   | "#["        { HASHLBRACKET }
  279.   | "]"         { RBRACKET }
  280.   | "("
  281.      { if not(Stack.null parCount) then
  282.          Stack.push (Stack.pop parCount + 1) parCount
  283.        else ();
  284.        LPAREN
  285.      }
  286.   | ")"
  287.       { if not(Stack.null parCount) then
  288.           let val count = Stack.pop parCount - 1 in
  289.             if count = 0 then
  290.               (lexingMode := QUOTElm; Token lexbuf)
  291.             else
  292.               (Stack.push count parCount; RPAREN)
  293.           end
  294.         else
  295.           RPAREN
  296.       }
  297.   | ";"         { SEMICOLON }
  298.   | (eof | `\^Z`) { EOF }
  299.   | ""          { if !quotation then TokenIdQ lexbuf else TokenId lexbuf }
  300.  
  301. and TokenId = parse
  302.     ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  303.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  304.        `~` `\`` `^` `|` `*`]+ )
  305.       { mkKeyword lexbuf }
  306.   | ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  307.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  308.        `~` `\`` `^` `|` `*`]+ )
  309.     "."
  310.     ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  311.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  312.        `~` `\`` `^` `|` `*`]+ )
  313.       { mkQualId lexbuf }
  314.   | _
  315.       { lexError "ill-formed token" lexbuf }
  316.  
  317. and TokenIdQ = parse
  318.     ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  319.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  320.        `~` `^` `|` `*`]+ )
  321.       { mkKeyword lexbuf }
  322.   | ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  323.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  324.        `~` `^` `|` `*`]+ )
  325.     "."
  326.     ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  327.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  328.        `~` `^` `|` `*`]+ )
  329.       { mkQualId lexbuf }
  330.   | "`"
  331.       { lexingMode := QUOTElm; QUOTEL }
  332.   | _
  333.       { lexError "ill-formed token" lexbuf }
  334.  
  335. and Comment = parse
  336.     "(*"
  337.       { (incr comment_depth; Comment lexbuf) }
  338.   | "*)"
  339.       { (decr comment_depth;
  340.          if !comment_depth > 0 then Comment lexbuf else ()) }
  341.   | (eof | `\^Z`)
  342.       { notTerminated "comment" lexbuf }
  343.   | _
  344.       { Comment lexbuf }
  345.  
  346. and String = parse
  347.     `"`
  348.       { () }
  349.   | `\\` [`\\` `"` `a` `b` `t` `n` `v` `f` `r`]
  350.       { store_string_char(char_for_backslash(getLexemeChar lexbuf 1));
  351.         String lexbuf }
  352.   | `\\` [` ` `\t` `\n` `\r`]+ `\\`
  353.       { String lexbuf }
  354.   | `\\` `^` [`@`-`_`]
  355.       { store_string_char(
  356.           Char.chr(Char.ord(getLexemeChar lexbuf 2) - 64));
  357.         String lexbuf }
  358.   | `\\` [`0`-`9`] [`0`-`9`] [`0`-`9`]
  359.       { let val code = charCodeOfDecimal lexbuf 1 in
  360.           if code >= 256 then
  361.             skipString "character code is too large" SkipString lexbuf
  362.           else ();
  363.           store_string_char(Char.chr code);
  364.           String lexbuf
  365.         end }
  366.   | `\\`
  367.       { skipString "ill-formed escape sequence" SkipString lexbuf }
  368.   | (eof | `\^Z`)
  369.       { notTerminated "string" lexbuf }
  370.   | [`\n` `\r`]
  371.       { skipString "newline not permitted in string" SkipString lexbuf }
  372.   | [`\^A`-`\^Z` `\127` `\255`]
  373.       { skipString "invalid character in string" SkipString lexbuf }
  374.   | _
  375.       { (store_string_char(getLexemeChar lexbuf 0);
  376.          String lexbuf) }
  377.  
  378. and SkipString = parse
  379.     `"`
  380.       { () }
  381.   | `\\` [`\\` `"` `n` `t`]
  382.       { SkipString lexbuf }
  383.   | `\\` [` ` `\t` `\n` `\r`]+ `\\`
  384.       { SkipString lexbuf }
  385.   | (eof | `\^Z`)
  386.       { notTerminated "string" lexbuf }
  387.   | _
  388.       { SkipString lexbuf }
  389.  
  390. and Quotation = parse
  391.     "`"
  392.       { lexingMode := NORMALlm }
  393.   | `^`
  394.       { lexingMode := ANTIQUOTElm }
  395.   | `\r`
  396.       { Quotation lexbuf }
  397.   | [`\t` `\n`]
  398.       { (store_string_char(getLexemeChar lexbuf 0);
  399.          Quotation lexbuf) }
  400.   | (eof | `\^Z`)
  401.       { lexingMode := NORMALlm;
  402.         notTerminated "quotation" lexbuf
  403.       }
  404.   | [`\^A`-`\^Z` `\127` `\255`]
  405.       { skipString "invalid character in quotation" SkipQuotation lexbuf }
  406.   | _
  407.       { (store_string_char(getLexemeChar lexbuf 0);
  408.          Quotation lexbuf) }
  409.  
  410. and SkipQuotation = parse
  411.     "`"
  412.       { lexingMode := NORMALlm }
  413.   | (eof | `\^Z`)
  414.       { lexingMode := NORMALlm;
  415.         notTerminated "quotation" lexbuf
  416.       }
  417.   | _
  418.       { SkipQuotation lexbuf }
  419.  
  420. and AntiQuotation = parse
  421.     ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*
  422.     | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`
  423.        `~` `|` `*`]+ )
  424.       { lexingMode := QUOTElm;
  425.         mkKeyword lexbuf
  426.       }
  427.   | "("
  428.       { Stack.push 1 parCount; lexingMode := NORMALlm;
  429.         TokenN lexbuf
  430.       }
  431.   | "`"
  432.       { lexingMode := NORMALlm;
  433.         lexError "antiquotation is missing" lexbuf
  434.       }
  435.   | (eof | `\^Z`)
  436.       { lexingMode := NORMALlm;
  437.         notTerminated "antiquotation" lexbuf
  438.       }
  439.   | _
  440.       { lexingMode := QUOTElm;
  441.         lexError "ill-formed antiquotation" lexbuf
  442.       }
  443. ;
  444.